/*
Flickr Photosets - Tagging Javascript
Handles tagging photos and videos (soon).

author Brad Dougherty <bdougherty@gmail.com>
version 8.5.22
license http://www.gnu.org/licenses/gpl.html GNU General Public License 3.0
*/

/*
The following variables will need to be provided
before including this file:

calbackUrl
uid
pid
frameWidth
frameHeight
frameBorder

photoWidth
photoHeight

The enableTagging() function must be run to initialize

*/

// Store the elements we will reference
var nameFrame = $('name_frame');
var tagFrame = $('tag_frame');
var tagFrameInside = $('tag_frame_inside');
var tagSelector = $('tag_selector');
var photoDiv = $('photo');
var thePhoto = $('thephoto'); // img tag
var thePhotoLink = $('thephoto_link'); // link tag
var tagMessage = $('tag_message');
var tagList = $('photo_tags');

var currentFrameIndex;
var tagging = false; // If the user is currently tagging
var taggingEnabled = false; // If tagging has been enabled
var tags = []; // List of tags

/*
Add a tag to the array
*/
function addTag(theXPct, theYPct, theNameContent, theTagId) {
	var centerX = Math.round(theXPct * thePhoto.getClientWidth());
	var centerY = Math.round(theYPct * thePhoto.getClientHeight());
	
	tags[tags.length] = {
		x: centerX,
		y: centerY,
		nameContent: theNameContent,
		tagId: theTagId.replace(/-/g, '')
	}
}

function cancelTag() {	
	tagFrame.setStyle('display', 'none');
	tagSelector.setStyle({top: '-10000px', left: '-10000px', display: 'none'});
}

// Add the listeners to the target
function enableTagging() {
	taggingEnabled = true;
	
	// Set the frame size
	tagFrame.setStyle({width: (frameWidth + (frameBorder / 2)) + 'px', height: (frameHeight + (frameBorder / 2)) + 'px'});
	tagFrameInside.setStyle({width: frameWidth + 'px', height: frameHeight + 'px'});	
	
	// Add the listeners for showing name frames
	//photoDiv.addEventListener('mousemove', findTag);
	thePhotoLink.addEventListener('mousemove', findTag);
	nameFrame.addEventListener('mousemove', stopPropagation);
	thePhoto.addEventListener('load', addTags);
}

/*
Find a tag as the mouse moves
*/
function findTag(event) {
	var mouseX = event.pageX - thePhoto.getAbsoluteLeft();
	var mouseY = event.pageY - thePhoto.getAbsoluteTop();
	var frameMinX = frameWidth / 2;
	var frameMinY = frameHeight / 2;
	
	var minDist = -1;
	var minIndex = -1;
	var dist;
	var dX;
	var dY;
	
	if (tags) {
		for (var i = 0; i < tags.length; i++) {
			dX = Math.abs(Math.min(Math.max(frameMinX, tags[i]['x']), thePhoto.getClientWidth() - frameMinX - frameBorder) - mouseX);
			dY = Math.abs(Math.min(Math.max(frameMinY, tags[i]['y']), thePhoto.getClientHeight() - frameMinY - frameBorder) - mouseY);
			if (dX < frameMinX && dY < frameMinY) {
				dist = Math.pow(dX, 2) + Math.pow(dY, 2);
				if (minDist == -1 || dist < minDist) {
					minDist = dist;
					minIndex = i;
				}
			}
		}
		if (minIndex != -1) {
			if (currentFrameIndex != minIndex) {
				showNameFrame(tags[minIndex]['x'], tags[minIndex]['y'], tags[minIndex]['nameContent'], tags[minIndex]['tagId']);
			}
		}
		else {
			hideNameFrame();
		}
		currentFrameIndex = minIndex;
	}
}

function frameClick(event) {
	if (tagging) {
		stopPropagation(event);
		var mouseX = event.pageX - thePhoto.getAbsoluteLeft();
		var mouseY = event.pageY - thePhoto.getAbsoluteTop();
		updateFrame(mouseX, mouseY, true);
	}
}

// Returns the position of the top left of the frame based off the center
function getAdjFrameX(centerX) {
	// Calculate some numbers we need for positioning
	var photoLeft = (photoDiv.getOffsetWidth() - thePhoto.getOffsetWidth()) / 2;
	var minX = photoLeft - frameBorder;
	var maxX = photoLeft + thePhoto.getClientWidth() - frameWidth - frameBorder;
	
	// Adjust the position so it describes the inside of the frame, not the border
	var posX = photoLeft + parseInt(centerX) - (frameWidth / 2) - frameBorder;
	
	// Calculate the actual position to place the tag frame
	// (relative to the left and top of the canvas area)
	return Math.round(Math.min(Math.max(minX, posX), maxX));
}

// Returns the position of the top left of the frame based off the center
function getAdjFrameY(centerY) {
	// Calculate some numbers we need for positioning
	var photoTop = thePhoto.getAbsoluteTop() - $('tag_message').getOffsetHeight() - (2 * frameBorder);
	var minY = photoTop - frameBorder + 1;
	var maxY = photoTop + thePhoto.getClientHeight() - frameHeight - frameBorder - safariAdjust; // Theres an extra pixel for whatever reason
	
	// Adjust the position so it describes the inside of the frame, not the border
	var posY = photoTop + parseInt(centerY) - (frameHeight / 2) - frameBorder;
	
	// Calculate the actual position to place the tag frame
	// (relative to the left and top of the canvas area)
	return Math.round(Math.min(Math.max(minY, posY), maxY));
}

/*
Hide the name frame
*/
function hideNameFrame() {
    nameFrame.setStyle('display', 'none');
}

/*
Hide the tag box
*/
function hideTag() {
	if (!tagging) {
		tagFrame.setStyle('display', 'none');
	}
}

function removeTags(tags, token) {
	
	var params = {
		'method': 'remove_tag',
		'uid': uid,
		'pid': pid,
		'tag_ids': tags, // Comma-separated
		'token': token
	};
	
	// Create the ajax object and make the call
	var removeAjax = new Ajax();
	removeAjax.responseType = Ajax.JSON;
	removeAjax.ondone = function(data) {
		if (data.success == 0) {
			showDialog(data);
		}
		else if (data.success = 1) {
			//updateTagList();
			tagList.setInnerFBML(data.fbml_taggedUsersString);
			tagList.removeClassName('hide');
			
			// Remove the tags from being displayed
			var tagsList = data.tag_ids.split(',');
			for (var i = 0; i < tags.length; i++) {
				for (var j = 0; j < tagsList.length; j++) {
					if (tagsList[j].replace(/-/g, '') == tags[i].tagId) {
						tags.splice(i, 1);
					}
				}
			}
			
		}
	};
	removeAjax.post(callbackUrl + '/ajax.php', params);
	
}

function roundDecimal(number, places) {
	return Math.round(number * Math.pow(10, places)) / Math.pow(10, places);
}

function showDialog(data) {
	var dialog = new Dialog(Dialog.DIALOG_POP);
	dialog.showMessage(data.title, data.fbml_content, data.button);
	dialog.onconfirm = function() {
		dialog.hide();
	};
}

/*
Show the name frame for a tag with this center
*/
function showNameFrame(centerX, centerY, context, theId) {
	if (typeof(tags) == 'undefined' || typeof(tags['id'+theId]) == 'undefined') {
		nameFrame.setInnerXHTML('<span>'+context+'</span>');
	}
	else {
		nameFrame.setInnerFBML(tags['id'+theId]);
	}
	nameFrame.setStyle({top: '-10000px', left: '-10000px', display: ''});
	
	// Get the adjusted position for the frame	
	var frameX = getAdjFrameX(centerX) + (Math.abs(frameWidth - nameFrame.getClientWidth()) / 2) + frameBorder;
	var frameY = getAdjFrameY(centerY) + frameHeight - nameFrame.getClientHeight();
	
	nameFrame.setStyle('left', Math.round(frameX) + 'px');
	nameFrame.setStyle('top', Math.round(frameY) + 'px');
}

/*
Show the tag frame at this position
*/
function showTagAt(centerXPct, centerYPct) {
	if (!tagging) {
		var centerX = Math.round(centerXPct * thePhoto.getClientWidth());
		var centerY = Math.round(centerYPct * thePhoto.getClientHeight());
		updateFrame(centerX, centerY, false);
	}
}

function startTagging() {
	if (!tagging && taggingEnabled) {
		tagging = true;
		
		// Prevent the link from working and change cursor
		thePhotoLink.addEventListener('click', preventDefault);
		thePhotoLink.setStyle('cursor', 'crosshair');
		
		// Add the click listener
		//photoDiv.addEventListener('click', frameClick);
		thePhotoLink.addEventListener('click', frameClick);
		
		Animation(tagMessage).to('height', 'auto').from('0px').to('opacity', 1).from(0).show().ease(Animation.ease.end).blind().duration(250).go();
	}
}

/*
Stop the propagation of an event
*/
function stopPropagation(event) {
	event.stopPropagation();
}

function stopTagging() {
	if (tagging) {
		tagging = false;
		
		// Reactivate link and reset cursor
		thePhotoLink.removeEventListener('click', preventDefault);
		thePhotoLink.setStyle('cursor', 'pointer');
		
		// Remove the click listener
		//photoDiv.removeEventListener('click', frameClick);
		thePhotoLink.removeEventListener('click', frameClick);
		
		// Hide the selector and frame
		tagFrame.setStyle('display', 'none');
		tagSelector.setStyle('display', 'none');
		Animation(tagMessage).to('height', '0px').to('opacity', 0).hide().ease(Animation.ease.end).blind().duration(250).go();
	}
}

function submitTag() {
	// Get the form and serialize the parameters
	var form = $('tag_form');
	var params = form ? form.serialize() : null;

	// Create the ajax object and make the call
	var addAjax = new Ajax();
	addAjax.responseType = Ajax.JSON;
	addAjax.ondone = function(data) {
		tagReturn(data);
	};
	addAjax.post(callbackUrl + '/ajax.php', params);
	
	// Hide the tag and selector
	cancelTag();
}

function tagReturn(data) {
	if (data.success == 1) {
		var content = (data.tag == '') ? data.tagContent : data.tag;
		addTag(data.tagX, data.tagY, data.tagContent, data.tagID);
		//updateTagList();
		tagList.setInnerFBML(data.fbml_taggedUsersString);
		tagList.removeClassName('hide');
	}
	else if (data.success == 0) {
		showDialog(data);
	}
}

// Place the frame using the center position
function updateFrame(centerX, centerY, withSelector) {
	tagFrameInside.setInnerXHTML('<span> </span>');
	
	var frameX = getAdjFrameX(centerX);
	var frameY = getAdjFrameY(centerY);
	
	$('photo_title').setInnerXHTML('<span>center y: '+centerY+', adj: '+frameY+'</span>');
	
	tagFrame.setStyle({left: frameX + 'px', top: frameY + 'px'})
	tagFrame.setStyle('display', '');
	
	if (withSelector) {
		
		// Convert pixels to percent
		var pctX = centerX / thePhoto.getClientWidth();
		var pctY = centerY / thePhoto.getClientHeight();
				
		// Reset the tag selector and set proper values
		tagSelector.setInnerFBML(tagFormContent);
		$('tag_x').setValue(roundDecimal(pctX, 3));
		$('tag_y').setValue(roundDecimal(pctY, 3));
		
		// Make sure the selector doesn't go off the edge
		//var selectorX = 
		
		
		if (frameX > (thePhoto.getClientWidth() / 2)) {
			frameX = frameX - frameBorder - 5 - tagSelector.getClientWidth(); // right side
		}
		else {
			frameX = frameX + frameWidth + frameBorder + 25; // left side
		}
		
		// Show it
		tagSelector.setStyle({top: Math.round(frameY) + 'px', left: Math.round(frameX) + 'px', display: ''});
		$('tag_form_text').getPreviousSibling().focus();
	}
	
}

function updateTagList() {
	var tagsAjax = new Ajax();
	tagsAjax.responseType = Ajax.FBML;
	tagsAjax.ondone = function(data) {
		tagList.setInnerFBML(data);
		tagList.removeClassName('hide');
	}
	tagsAjax.post(callbackUrl + '/ajax.php?method=refresh_tag_list&uid='+uid+'&pid='+pid);
}